3. alsa中的文件(第二部分)

您所在的位置:网站首页 alsa compress 3. alsa中的文件(第二部分)

3. alsa中的文件(第二部分)

2023-11-05 12:25| 来源: 网络整理| 查看: 265

​​​​​​3.3 snd_device_ops

我们先辨别两个函数:snd_register_device 与snd_device_register。snd_register_device在前面已经介绍过了,负责保存snd_minor对象。snd_device_register其实里也是为这个目的存在的,最后它会调用到snd_register_device。

直接调用snd_register_device有以下一些函数:

snd_pcm_dev_register

注册pcm设备

snd_ctl_dev_register

注册control设备

snd_rawmidi_dev_register

注册midi设备

snd_compress_dev_register

注册支持解压缩的设备

snd_hwdep_dev_register

注册硬件设备

alsa_timer_init

注册时间设备

snd_sequencer_device_init

注册序列设备

每种设备都有各自的注册函数,因为有一些不同的操作需要处理。以上函数中时间和序列设备比较特殊,设备生成的时候直接注册就好了。

而其它几类设备在生成设备的时候并没有直接注册,而是在所有部件都准备好之后,统一去注册的。这也就是为什么需要snd_device_ops的原因,先看下定义:

struct snd_device_ops { int (*dev_free)(struct snd_device *dev); int (*dev_register)(struct snd_device *dev); int (*dev_disconnect)(struct snd_device *dev); };

 再看看它的用法,以control设备为例,比较简单点。

int snd_ctl_create(struct snd_card *card) { static const struct snd_device_ops ops = { .dev_free = snd_ctl_dev_free, .dev_register = snd_ctl_dev_register, .dev_disconnect = snd_ctl_dev_disconnect, }; int err; if (snd_BUG_ON(!card)) return -ENXIO; if (snd_BUG_ON(card->number < 0 || card->number >= SNDRV_CARDS)) return -ENXIO; snd_device_initialize(&card->ctl_dev, card); dev_set_name(&card->ctl_dev, "controlC%d", card->number); err = snd_device_new(card, SNDRV_DEV_CONTROL, card, &ops); if (err < 0) put_device(&card->ctl_dev); return err; }

这段函数中可以看到初始化了一个snd_device_ops对象,其中dev_register指向我们提到过的snd_ctl_dev_register,它负责最终的设备注册。而ops最终会通过snd_device_new被保存到snd_device中,snd_device的定义如下:

struct snd_device { struct list_head list; /* list of registered devices */ struct snd_card *card; /* card which holds this device */ enum snd_device_state state; /* state of the device */ enum snd_device_type type; /* device type */ void *device_data; /* device structure */ const struct snd_device_ops *ops; /* operations */ };

这里可以看到它保存了一个snd_device_ops对象。

回看snd_device_register函数,先看它的两级函数:

static int __snd_device_register(struct snd_device *dev) { if (dev->state == SNDRV_DEV_BUILD) { if (dev->ops->dev_register) { int err = dev->ops->dev_register(dev); if (err < 0) return err; } dev->state = SNDRV_DEV_REGISTERED; } return 0; }

可以看到它会去调用注册的dev_register函数。

int snd_device_register(struct snd_card *card, void *device_data) { struct snd_device *dev; if (snd_BUG_ON(!card || !device_data)) return -ENXIO; dev = look_for_dev(card, device_data); if (dev) return __snd_device_register(dev); snd_BUG(); return -ENXIO; }

其实就是对 __snd_device_register的调用。这个函数一般不会用到,只是一些特殊的设备可能回去用。真正使用的是下面这个函数:

int snd_device_register_all(struct snd_card *card) { struct snd_device *dev; int err; if (snd_BUG_ON(!card)) return -ENXIO; list_for_each_entry(dev, &card->devices, list) { err = __snd_device_register(dev); if (err < 0) return err; } return 0; }

遍历snd_card中的所有设备,然后注册它。而这个函数也只在snd_card_register中被调用到。snd_card_register是alsa框架提供给外部使用的函数,具体的驱动程序在所有的工作处理完成后,必须调用该函数。相应的snd_device_register_all也肯定会被调用。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3